/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * 注意：
 * 本软件为www.yixiang.co开发研制
 */
package co.yixiang.modules.shop.service.impl;

import cn.hutool.crypto.SecureUtil;
import co.yixiang.modules.shop.domain.ExpressArea;
import co.yixiang.modules.shop.domain.ExpressPlan;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.modules.shop.domain.ExpressPlanDetail;
import co.yixiang.modules.shop.domain.YxStoreCart;
import co.yixiang.modules.shop.service.ExpressAreaService;
import co.yixiang.modules.shop.service.ExpressPlanDetailService;
import co.yixiang.modules.shop.service.dto.ExpressAreaDto;
import co.yixiang.modules.shop.service.dto.ExpressPlanDetailDto;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.AllArgsConstructor;
import co.yixiang.dozer.service.IGenerator;
import com.github.pagehelper.PageInfo;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.utils.FileUtil;
import co.yixiang.modules.shop.service.ExpressPlanService;
import co.yixiang.modules.shop.service.dto.ExpressPlanDto;
import co.yixiang.modules.shop.service.dto.ExpressPlanQueryCriteria;
import co.yixiang.modules.shop.service.mapper.ExpressPlanMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.function.Consumer;

/**
 * @author chajiu
 * @date 2021-04-25
 */
@Service
@AllArgsConstructor
//@CacheConfig(cacheNames = "ExpressPlan")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ExpressPlanServiceImpl extends BaseServiceImpl
        <ExpressPlanMapper, ExpressPlan> implements ExpressPlanService {

    private final IGenerator generator;
    private final ExpressPlanDetailService planDetailService;
    private final ExpressAreaService areaService;

    @Override
    public BigDecimal calPostage(YxStoreCart cart, Integer tempId) {
        // TODO: 2021/4/28 计算邮费
        return BigDecimal.valueOf(10);
    }

    @Override
    public void saveCascade(ExpressPlanDto planDto) {
        final String planUnique = SecureUtil.md5(planDto.toString());
        planDto.setUniqueId(planUnique);
        planDto.getPlanDetailDtoList().forEach(new Consumer<ExpressPlanDetailDto>() {
            @Override
            public void accept(ExpressPlanDetailDto detailDto) {
                //设置上层id
                detailDto.setPlanId(planUnique);
                //设置本层uniqueID
                final String detailUnique = SecureUtil.md5(detailDto.toString());
                detailDto.setUniqueId(detailUnique);

                detailDto.getAreaDtoList().forEach(new Consumer<ExpressAreaDto>() {
                    @Override
                    public void accept(ExpressAreaDto expressAreaDto) {
                        expressAreaDto.setDetailId(detailUnique);
                        //保存区域
                        areaService.save(generator.convert(expressAreaDto,ExpressArea.class));
                    }
                });
                //保存细节
                planDetailService.save(generator.convert(detailDto,ExpressPlanDetail.class));
            }
        });
        //保存方案
        if(planDto.getId()!=null){
            updateById(generator.convert(planDto, ExpressPlan.class));
        }else{
            save(generator.convert(planDto, ExpressPlan.class));
        }

    }

    @Override
    public void deleteCascade(ExpressPlanDto expressPlanDto) {
        String planDtoUnique = expressPlanDto.getUniqueId();
        //该计划下的详情
        LambdaQueryWrapper<ExpressPlanDetail> queryWrapper = new LambdaQueryWrapper<ExpressPlanDetail>()
                .eq(ExpressPlanDetail::getPlanId, planDtoUnique);
        List<ExpressPlanDetail> planDetailList = planDetailService.list(queryWrapper);
        planDetailList.forEach(new Consumer<ExpressPlanDetail>() {
            @Override
            public void accept(ExpressPlanDetail expressPlanDetail) {
                //    删除区域
                areaService.remove(new LambdaQueryWrapper<ExpressArea>()
                .eq(ExpressArea::getDetailId,expressPlanDetail.getUniqueId()));
            }
        });
        //删除详情
        planDetailService.remove(queryWrapper);

    //    删除计划
    //     removeById(expressPlanDto.getId());
    }

    @Override
    public void deleteCascade(ExpressPlan expressPlan) {
        deleteCascade(generator.convert(expressPlan,ExpressPlanDto.class));
    }

    @Override
//@Cacheable
    public Map <String, Object> queryAll(ExpressPlanQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<ExpressPlan> page = new PageInfo<>(queryAll(criteria));
        Map <String, Object> map = new LinkedHashMap<>(2);
        List<ExpressPlanDto> convert = generator.convert(page.getList(), ExpressPlanDto.class);
        final StringBuilder planAreaStringBuilder = new StringBuilder();

        //设置适用区域
        convert.forEach(new Consumer<ExpressPlanDto>() {
            @Override
            public void accept(ExpressPlanDto planDto) {
                List<ExpressPlanDetail> detailList = planDetailService.list(new LambdaQueryWrapper<ExpressPlanDetail>()
                        .eq(ExpressPlanDetail::getPlanId, planDto.getUniqueId()));
                List<ExpressPlanDetailDto> detailConvert = generator.convert(detailList, ExpressPlanDetailDto.class);

                final StringBuilder detailAreaStringBuilder = new StringBuilder();
                //查询每个detail的区域
                detailConvert.forEach(new Consumer<ExpressPlanDetailDto>() {
                    @Override
                    public void accept(ExpressPlanDetailDto detailDto) {
                        List<ExpressArea> areaList = areaService.list(new LambdaQueryWrapper<ExpressArea>()
                                .eq(ExpressArea::getDetailId, detailDto.getUniqueId()));
                        //添加区域到字符串
                        areaList.forEach(new Consumer<ExpressArea>() {
                            @Override
                            public void accept(ExpressArea expressArea) {
                                planAreaStringBuilder.append(expressArea.getAreaName());
                                planAreaStringBuilder.append(",");

                                detailAreaStringBuilder.append(expressArea.getAreaName());
                                detailAreaStringBuilder.append(",");
                            }
                        });
                        detailDto.setAreaDtoList(generator.convert(areaList, ExpressAreaDto.class));
                        if(detailAreaStringBuilder.length()>0){
                            detailDto.setAvailableArea(detailAreaStringBuilder.substring(0,detailAreaStringBuilder.length()-1));
                        }else{
                            detailDto.setAvailableArea("");
                        }
                        //清空stringBuilder
                        detailAreaStringBuilder.setLength(0);
                    }
                });
                planDto.setPlanDetailDtoList(detailConvert);
                if(planAreaStringBuilder.length()>0){
                    planDto.setAvailableArea(planAreaStringBuilder.substring(0, planAreaStringBuilder.length()-1));
                }else{
                    planDto.setAvailableArea("");
                }
                //清空stringBuilder
                planAreaStringBuilder.setLength(0);
            }
        });

        map.put("content", generator.convert(convert, ExpressPlanDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }


    @Override
//@Cacheable
    public List<ExpressPlan> queryAll(ExpressPlanQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(ExpressPlan.class, criteria));
    }


    @Override
    public void download(List
                                 <ExpressPlanDto> all, HttpServletResponse response) throws IOException {
        List
                <Map
                        <String
                                , Object>> list = new ArrayList<>();
        for (ExpressPlanDto ExpressPlan : all) {
            Map
                    <String
                            , Object> map = new LinkedHashMap<>();
            map.put("门店id", ExpressPlan.getStoreId());
            map.put("方案名称", ExpressPlan.getName());
            map.put("计费方式 0按件 1按重量 2包邮", ExpressPlan.getType());
            map.put("是否全国统一 0不是 1是", ExpressPlan.getIsCountry());
            map.put("添加时间", ExpressPlan.getSubmitTime());
            map.put("更新时间", ExpressPlan.getUpdateTime());
            map.put("唯一ID", ExpressPlan.getUniqueId());
            map.put("唯一ID", ExpressPlan.getUniqueId());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
